<?php

if(!defined('OI')) {
			
	print '<h1>Access Error</h1>Sorry, this file can not be accessed directly, this is strictly forbidden!';
	exit();
				
}

class Book {

	# Store digitalUniversity
	private $digitalUniversity = NULL;
	private $hadEmptyBook = false;
	private $bookChanges = false;

	/*
	 * Constructor: Store instance of sitebuilder
	 * 	- PHP5 now uses pass by reference so we do not need to store the reference
	*/
	public function __construct(DigitalUniversity &$digitalUniversity) {
	
		$this->digitalUniversity =& $digitalUniversity;
				
	}
	
	/*
	 * Destructor: Clean memory parts
	*/
	public function __destruct() {
		
		unset($this->digitalUniversity);
		
	}	
	
	/*
	 * getRatings: Get all ratings for a given resource.
	 *
	 * @return array - Resource ratings
	*/
	private function getRatings() {
	
		# Particular module
		$ratings = $this->digitalUniversity->db->getRow("SELECT COUNT(*) as totalVotes, SUM(rating) as sumVotes, (
			SELECT userID FROM books_ratings
			WHERE ISBN = '{$this->digitalUniversity->input['book']}' AND userID = '{$this->digitalUniversity->user['userID']}'
		) AS userHasVoted FROM books_ratings 
		WHERE ISBN = '{$this->digitalUniversity->input['book']}'");
						
		return $ratings;			
		
	}
	
	/*
	 * getComments: Get all comments for a given resource.
	 *
	 * @return array - Resource comments
	*/
	private function getComments() {
	
		# Particular module
		$comments = $this->digitalUniversity->db->getResults("SELECT c.*, u.firstName, u.surname, u.username FROM books_comments bc
		LEFT JOIN comments c ON (c.commentID = bc.commentID)
		LEFT JOIN users u ON (u.userID = c.userID)
		WHERE bc.ISBN = '{$this->digitalUniversity->input['book']}' AND c.status = '1'
		ORDER BY time DESC
		LIMIT 20");
		
		return $comments;			
		
	}
	
	private function getBooks($limit = 8) {
		
		# Get books on loan
		$books = $this->digitalUniversity->db->getResults("SELECT * FROM books
		WHERE title != ''
		ORDER BY RAND()
		LIMIT {$limit}");
			
		return $books;
			
	}
	
	private function getBook() {
		
		# Get books on loan
		$book = $this->digitalUniversity->db->getRow("SELECT * FROM books b
		WHERE b.ISBN = '{$this->digitalUniversity->input['book']}'
		LIMIT 1");
		
		return $book;
			
	}
	
	private function scrapeBookDetails(&$book, &$time) {
		
		# Create book
		if(empty($book)) {
			$book['ISBN'] = $this->digitalUniversity->input['book'];
			$this->hadEmptyBook = true;
		}
			
		# Google Books API - details
		$isbnURL = 'https://www.googleapis.com/books/v1/volumes?q=ISBN:'.$book['ISBN'];
							
		$ch = curl_init();			
			curl_setopt($ch, CURLOPT_URL, $isbnURL);
			curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
			curl_setopt($ch, CURLOPT_TIMEOUT, 3);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		$googleResults = json_decode(curl_exec($ch), true);												
		curl_close($ch);	
				
		# Open Library - images			
		$isbnURL = 'http://openlibrary.org/api/books?bibkeys=ISBN:'.$book['ISBN'].'&jscmd=data&format=json';
							
		$ch = curl_init();			
			curl_setopt($ch, CURLOPT_URL, $isbnURL);
			curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
			curl_setopt($ch, CURLOPT_TIMEOUT, 3);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		$openLibraryResults = json_decode(curl_exec($ch), true);												
		curl_close($ch);									
								
		if(!empty($googleResults) && ($googleResults['totalItems'] != 0)) {	
					
			if(empty($bookDetails) || empty($bookDetails['title'])) {
				$bookDetails = $googleResults['items'][0]['volumeInfo'];
				$this->bookChanges = true;
			}
			
		} else {
			
			return array(false, '<h5>No results were found matching this book</h5>');
					
		}
																
		if(!empty($openLibraryResults)) {
			if(empty($bookDetails['thumbnail_large'])) {
				if(!empty($openLibraryResults['ISBN:'.$book['ISBN']]['cover'])) {
					$bookDetails['thumbnail_large'] = $openLibraryResults['ISBN:'.$book['ISBN']]['cover']['large'];
					$bookDetails['thumbnail_medium'] = $openLibraryResults['ISBN:'.$book['ISBN']]['cover']['medium'];
					$bookDetails['thumbnail_small'] = $openLibraryResults['ISBN:'.$book['ISBN']]['cover']['small'];
				}
				$this->bookChanges = true;
			}
			if(empty($bookDetails['openURL'])) {
				$bookDetails['openURL'] = $openLibraryResults['ISBN:'.$book['ISBN']]['url'];
				$this->bookChanges = true;
			}
			if(empty($bookDetails['identifiers'])) {
				$bookDetails['identifiers'] = $openLibraryResults['ISBN:'.$book['ISBN']]['identifiers'];
				$this->bookChanges = true;
			}
		}
				
		# Update cache time
		if(!$this->bookChanges && !$this->hadEmptyBook) {
								
			$this->digitalUniversity->db->query("UPDATE books SET cacheTime = '{$time}'
			WHERE ISBN = '{$this->digitalUniversity->input['book']}' LIMIT 1");
						
		}
		
		return array(true, $bookDetails);
				
	}
	
	private function saveBookChanges(&$bookDetails, &$time) {
		
		# Safety slashes
		$bookDetails['description'] = addslashes(htmlentities($bookDetails['description'], ENT_QUOTES, 'UTF-8'));
				
		# Title slashes
		$bookDetails['title'] = addslashes(htmlentities($bookDetails['title'], ENT_QUOTES, 'UTF-8'));
				
		# Subtitle slashes
		if(!empty($bookDetails['subtitle'])) {
			$bookDetails['subtitle'] = addslashes(htmlentities($bookDetails['subtitle'], ENT_QUOTES, 'UTF-8'));
		}
			
		# Serialize				
		$bookDetailsCompressed = str_replace('//', '/', json_encode($bookDetails));	
				
		# Store title
		if(!empty($bookDetails['subtitle'])) {
			$storeTitle = $bookDetails['title'].', '.$bookDetails['subtitle'];		
		} else {
			$storeTitle = $bookDetails['title'];
		}
			
		if($this->hadEmptyBook) {
								
			# Update query
			$this->digitalUniversity->db->query("INSERT INTO books SET cacheTime = '{$time}', details = '{$bookDetailsCompressed}', title = '{$storeTitle}', ISBN = '{$this->digitalUniversity->input['book']}', copies = 5, available = 1, publisher = '{$bookDetails['publisher']}', description = '{$bookDetails['description']}'");
					
		} else {
			
			# Update query
			$this->digitalUniversity->db->query("UPDATE books SET cacheTime = '{$time}', details = '{$bookDetailsCompressed}'
			WHERE ISBN = '{$this->digitalUniversity->input['book']}'
			LIMIT 1");
									
		}
								
		# Clean memory
		unset($bookDetailsCompressed, $bookDetails);
				
	}
	
	private function showRatings(&$bookID) {
		
		# Get ratings
		$ratings = $this->getRatings();
		
		# Define variables
		$average = 0;
		$width = 0;
		$userHasVoted = false;
		$class = '';
		
		# Any ratings?
		if(!empty($ratings)) {
			
			# Average rating
			$average = ($ratings['totalVotes'] != 0 ? $ratings['sumVotes'] / $ratings['totalVotes'] : 0);
			
			# Width of stars
			if($average != 0) {
				$width = (($average * 2) * 10 + ((ceil($average) - 1) * 10));
			}
						
			# Has the user voted?
			if($ratings['userHasVoted'] == $this->digitalUniversity->user['userID']) {
				$userHasVoted = true;	
			}
			
		}
		
		if($userHasVoted) {
			$class = ' inactive';
		}
		
		echo '<h4>Rating</h4>
		<section class="contentBlock clearfix ratingBlock"  id="ratingSubmit" data-book="'.$bookID.'" data-type="book"'.($userHasVoted ? ' data-disabled="true"' : '').'>
			<div class="rating">
				<div class="darkStar" style="width: '.$width.'px;">&nbsp;</div>
				<div class="lightStar star_1'.$class.'" data-rating="1">&nbsp;</div>
				<div class="lightStar star_2'.$class.'" data-rating="2">&nbsp;</div>
				<div class="lightStar star_3'.$class.'" data-rating="3">&nbsp;</div>
				<div class="lightStar star_4'.$class.'" data-rating="4">&nbsp;</div>
				<div class="lightStar star_5'.$class.'" data-rating="5">&nbsp;</div>
				<div class="percentage">'.$average.'</div>
			</div>';
			if($average != 0) {
				echo '<h3 class="votesCast">'.$ratings['totalVotes'].' vote'.(($ratings['totalVotes'] != 1) ? 's' : '').' cast</h3>';	
			}
			if(!$userHasVoted) {
				echo '
				<div class="voteButtonContainer">
					<div class="ratingButton" data-rating="1">1</div>
					<div class="ratingButton" data-rating="2">2</div>
					<div class="ratingButton" data-rating="3">3</div>
					<div class="ratingButton" data-rating="4">4</div>
					<div class="ratingButton ratingButtonLast" data-rating="5">5</div>
				</div>';
			}
		echo '</section>';
			
	}
	
	/*
	 * loadPage: Detect the current page being viewed and output the relevant
	 * page contents
	*/
	public function outputPage() {
		
		# Can administrate
		if($this->digitalUniversity->user['groupLevel'] >= 3) {
			$canAdmin = true;	
		} else {
			$canAdmin = false;
		}
		
		# Get the book
		if($canAdmin && isset($this->digitalUniversity->post['addNewBook'])) {
			
			$this->digitalUniversity->input['book'] = $this->digitalUniversity->post['isbn'];	
			
		} elseif($canAdmin && isset($this->digitalUniversity->post['assignBook'])) {
		
			$this->digitalUniversity->db->query("INSERT INTO modules_books SET moduleID = '{$this->digitalUniversity->post['module']}', ISBN = '{$this->digitalUniversity->input['book']}'");
			
			return $this->digitalUniversity->redirect('book&book='.$this->digitalUniversity->input['book'].'&act=assigned');
			
		}
		
		$this->digitalUniversity->addPageTree('Books', $this->digitalUniversity->config['scripturl'].'page=book');
		
		# All books or specific?
		if(empty($this->digitalUniversity->input['book'])) {
		
			# Get books
			$books = $this->getBooks();
						
			echo '<section class="fullPageWidth">
				<h1>Books</h1>
				<nav class="pageTab">
					<a class="focus" href="#" data-tab="books">Available</a>
					'.($canAdmin ? '<a href="#" data-tab="administrate">Administrate</a>' : '').'
					<a class="right" href="'.$this->digitalUniversity->config['scripturl'].'page=modules" data-tab="notabber">Modules</a>
					<a class="right" href="'.$this->digitalUniversity->config['scripturl'].'page=resources" data-tab="notabber">Resources</a>
				</nav>
				
				'.($canAdmin ? '
				<section id="tab_administrate" class="dataTab hidden">					
					<section class="contentBlock clearfix addNewResource">
						<form action="'.$this->digitalUniversity->config['scripturl'].'page=book&act=create" method="post">
							<p class="noUpper">
								<label for="isbn">ISBN:</label> <input type="text" value="" id="isbn" name="isbn" />
							</p>
							<input type="submit" class="submitButton" name="addNewBook" value="Add Book" />
						</form>				
					</section>				
				</section>' : '').'
				
				<section class="contentBlock clearfix">';
					
					# Are we lending anything?
					if(!empty($books)) {
					
						foreach($books as $k => $v) {
						
							if(($k+1) % 7 == 0) {
								$class = ' lastChild';
							} else {
								$class = '';
							}
						
							echo '<a href="'.$this->digitalUniversity->config['scripturl'].'page=book&book='.$v['ISBN'].'">
								<article class="document book'.$class.'">							
									<h5 class="title">'.$v['title'].'</h5>
								</article>
							</a>';
							
						}
						
					}
														 
				echo '</section>				
			</section>';
		
		} else {
			
			# Get the book
			$book = $this->getBook();
			
			if(!empty($book) && !empty($book['title'])) {
				$this->digitalUniversity->addPageTree($book['title'], $this->digitalUniversity->config['scripturl'].'page=book&book='.$book['ISBN']);
			}
			
			# Define variables
			$time = time();
			
			# Display title
			if(!empty($book['title'])) {
				if(strlen($book['title']) > 57) {
					$displayTitle = substr($book['title'], 0, 54).'..';	
				} else {
					$displayTitle = $book['title'];
				}
			}
			
			# Renewing book
			if(!empty($this->digitalUniversity->input['act']) && ($this->digitalUniversity->input['act'] == 'renew')) {
			
				# Does the user have this book?
				$userBook = $this->digitalUniversity->db->getRow("SELECT * FROM users_books 
				WHERE userID = '{$this->digitalUniversity->user['userID']}' AND ISBN = '{$book['ISBN']}' AND returnTime < '{$time}'
				LIMIT 1");
				
				# Any results?
				if(!empty($userBook)) {
				
					# Is the book available?
					if($book['available'] == 0) {
					
						# Redirect
						return $this->digitalUniversity->redirect('book&book='.$book['ISBN'].'&act=error&message=This book is currently on hold by another user and must be returned as soon as possible.');
						
					} else {				
							
						# Update book
						$this->digitalUniversity->db->query("UPDATE users_books SET returnTime = (returnTime + (60*60*24*7))
						WHERE userID = '{$this->digitalUniversity->user['userID']}' AND ISBN = '{$book['ISBN']}' 
						LIMIT 1");
						
						# Redirect
						return $this->digitalUniversity->redirect('book&book='.$book['ISBN'].'&act=renewed&timestamp='.($userBook['returnTime'] + (60*60*24*7)));
						
					}
				
				}
				
			}
			
			echo '<section class="leftColumn">
				'.(!empty($displayTitle) ? '<h1>'.$displayTitle.'</h1>' : '').'
				<nav class="pageTab">
					<a class="focus" href="#" data-tab="description">Description</a>					
					<a href="#" data-tab="details">Details</a>
				</nav>';
				
				# <a href="#" data-tab="availablity">Availablity</a>
			
				# Unserialize details
				if(!empty($book['details'])) {
					$bookDetails = json_decode(stripslashes($book['details']), true);
				}
							
				# Do we have details?
				if((empty($bookDetails) || empty($bookDetails['title']) || ($book['cacheTime'] < $time - (60*60*24*7))) && $canAdmin) {
				
					# Raw process results
					$bookDetailsRaw = $this->scrapeBookDetails($book, $time);
					
					# Any errors?
					if($bookDetailsRaw[0] !== true) {
						
						echo $bookDetailsRaw[1];
						return false;
							
					} else {
						
						$bookDetails = $bookDetailsRaw[1];
						
					}
				
				}
				
				if(!empty($this->digitalUniversity->input['act'])) {
				
					if($this->digitalUniversity->input['act'] == 'renewed') {
						
						echo '<p class="noticeBox"><strong>Success:</strong> '.(!empty($this->digitalUniversity->input['message']) ? $this->digitalUniversity->input['message'] : 'This book has been renewed for 7 days'.(!empty($this->digitalUniversity->input['timestamp']) ? ' and is due back on '.date('F j, Y, g:i a', $this->digitalUniversity->input['timestamp']) : '')).'</p>';
							
					} elseif($this->digitalUniversity->input['act'] == 'error') {
						
						echo '<p class="noticeBox"><strong>Warning:</strong> '.(!empty($this->digitalUniversity->input['message']) ? $this->digitalUniversity->input['message'] : 'An error occurred while renewing this book.').'</p>';
							
					} elseif($this->digitalUniversity->input['act'] == 'assigned') {
					
						echo '<p class="noticeBox"><strong>Success:</strong> This book has been assigned to the specified module.</p>';
						
					}
					
				}
								
				# Output details																	
				echo '	
				<section id="tab_description" class="dataTab">
					<section class="contentBlock clearfix mainArticle">
						<img class="bookCover" src="'.(!empty($bookDetails['thumbnail_large']) ? $bookDetails['thumbnail_large'] : $bookDetails['imageLinks']['thumbnail']).'" alt="'.$bookDetails['title'].'"/>
						<h1>'.$bookDetails['title'].'</h1>
						'.(!empty($bookDetails['subtitle']) ? '<h5>'.$bookDetails['subtitle'].'</h5>' : '').'
						<p>'.html_entity_decode($bookDetails['description'], ENT_QUOTES, 'UTF-8').'</p>
					</section>
				</section>
				
				<section id="tab_availablity" class="dataTab hidden">
				
				</section>
				
				<section id="tab_details" class="dataTab hidden">
					<section class="contentBlock bookDetails">
						<table>';
						
							# Keys to display
							$allowedKeys = explode(', ', 'title, subtitle, authors, publisher, publishedDate, pageCount, printType, previewLink, infoLink, openURL, imageLinks, identifiers');						
							
							# Loop through display
							foreach($allowedKeys as $k => $v) {
								
								# Friendly text key
								$key = ucfirst(preg_replace('/([A-Z])/', ' $1', $v));
								
								# Skip empty keys
								if(empty($bookDetails[$v])) {
									continue;
								}
								
								echo '<tr>
									<td>'.$key.'</td>
									<td>';
																	
								# Array - authors, imageLinks, identifiers
								if(is_array($bookDetails[$v])) {								
																	
									if($v == 'authors') {
										
										echo implode(', ', $bookDetails[$v]);	
										
									} elseif($v == 'imageLinks') {
										
										# Temporary array
										$imageLinks = array();
										
										# Check each one
										if(!empty($bookDetails['thumbnail_large'])) {
											$imageLinks[] = '<a href="'.$bookDetails['thumbnail_large'].'" target="_blank">large</a>'; 
										}
										
										if(!empty($bookDetails['thumbnail_medium'])) {
											$imageLinks[] = '<a href="'.$bookDetails['thumbnail_medium'].'" target="_blank">thumbnail</a>'; 
										} else {
											$imageLinks[] = '<a href="'.$bookDetails['imageLinks']['thumbnail'].'" target="_blank">thumbnail</a>'; 
										}
										
										if(!empty($bookDetails['thumbnail_small'])) {
											$imageLinks[] = '<a href="'.$bookDetails['thumbnail_small'].'" target="_blank">small</a>'; 
										} else {
											$imageLinks[] = '<a href="'.$bookDetails['imageLinks']['smallThumbnail'].'" target="_blank">small</a>'; 
										}
										
										# Output links
										echo implode(', ', $imageLinks);
										
										# Clean memory
										unset($imageLinks);
										
									} elseif($v == 'identifiers') {								
									
										foreach($bookDetails[$v] as $ik => $iv) {
										
											echo '<strong>'.$ik.'</strong>:'.$iv[0].'<br />';
											
										}
										
									}
									
								} else {
																	
									if($v == 'previewLink' || $v == 'infoLink' || $v == 'openURL') {
										echo '<a href="'.$bookDetails[$v].'" target="_blank">external URL</a>';	
									} else {
										echo $bookDetails[$v];	
									}
										
								}
																	
								echo '</td>
								</tr>';
									
							}
																				
						echo '</table>      
					</section>
				</section>';	
				
				# Get comments
				$comments = $this->getComments();
					
				# Resource comments
				echo '<h4>Comments</h4>
				<section class="contentBlock clearfix">
					<section class="commentsContainer" id="commentsContainer">';
					
					# Do we have any comments?
					if(!empty($comments)) {
							
						foreach($comments as $k => $v) {
							
							echo '<article>
								<h5>
									<aside>'.$this->digitalUniversity->timeSince($v['time']).'</aside>
									'.$v['firstName'].' '.$v['surname'].'
								</h5>
								<p>'.html_entity_decode($v['comment'], ENT_QUOTES, 'UTF-8').'</p>
							</article>';
								
							}
						
					} else {
					
						echo '<article id="noComments">
							<p>This book has no comments.</p>
						</article>';
							
					}
						
				echo '<textarea name="commentEntryInput" title="Enter a comment.." placeholder="Enter a comment.." data-type="book" data-book="'.$book['ISBN'].'"></textarea>
					<p class="tip"><strong>Tip:</strong> Use the enter key to save your comment. CTRL + Enter produces a new line.</p>
					</section>
				</section>
			</section>
			
			<section class="rightColumn">';	
			
				# Display ratings
				if(!empty($book)) {
					
					$this->showRatings($book['ISBN']);
					
					# Lecturer
					if($this->digitalUniversity->user['groupLevel'] == 3) {
						
						# Own modules
						$ownModules = $this->digitalUniversity->db->getResults("SELECT * FROM modules WHERE lecturer = '{$this->digitalUniversity->user['userID']}'");
						
						if(!empty($ownModules)) {
							
							echo '<h4>Add to module</h4>
							<section class="contentBlock addNewResource clearfix">
								<form action="'.$this->digitalUniversity->config['scripturl'].'page=book&book='.$book['ISBN'].'" method="post">
									<p class="noUpper">If this book is relevant to the module you\'re teaching, you can assign it to the module.</p>
									<p class="fileField">
										<label for="module" style="width: 100px;">Module:</label>
										<select name="module" id="module">';
											foreach($ownModules as $k => $v) {
												echo '<option value="'.$v['moduleID'].'">'.$v['code'].'</option>';
											}
										echo '</select>
									</p>
									<input type="submit" class="submitButton" name="assignBook" value="Assign Book" />
								</form>
							</section>';
							
						}
						
					}
					
				}
						
			echo '</section>';
			
			# Did we make changes?
			if($this->bookChanges) {
			
				$this->saveBookChanges($bookDetails, $time);
																
			}	
			
		}				
										
	}
		
}

?>